/*-------------------------------------------------------------------------
 *
 * assert.c
 *	  断言支持代码。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/backend/utils/error/assert.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include <unistd.h>
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif

/*
 * ExceptionalCondition - 处理 Assert() 的失败
 *
 * 我们故意不通过 elog()，理由是希望最小化
 * 必须正常工作以报告断言失败的基础设施量。
 */
void ExceptionalCondition(const char *fc_conditionName,
					 const char *fc_errorType,
					 const char *fc_fileName,
					 int fc_lineNumber)
{
	/* 在 stderr（或本地等效处）报告失败 */
	if (!PointerIsValid(fc_conditionName)
		|| !PointerIsValid(fc_fileName)
		|| !PointerIsValid(fc_errorType))
		write_stderr("TRAP: ExceptionalCondition: bad arguments in PID %d\n",
					 (int) getpid());
	else
		write_stderr("TRAP: %s(\"%s\", File: \"%s\", Line: %d, PID: %d)\n",
					 fc_errorType, fc_conditionName,
					 fc_fileName, fc_lineNumber, (int) getpid());

	/* 通常这不应该是必要的，但确保消息已发送 */
	fflush(stderr);

	/* 如果我们有支持，转储一个简单的回溯 */
#ifdef HAVE_BACKTRACE_SYMBOLS
	{
		void	   *fc_buf[100];
		int			fc_nframes;

		fc_nframes = backtrace(fc_buf, lengthof(fc_buf));
		backtrace_symbols_fd(fc_buf, fc_nframes, fileno(stderr));
	}
#endif

	/*
	 * 如果配置为这样，永远睡眠以允许用户附加一个
	 * 调试器。 在这里使用 pg_usleep() 会很好，但它最多可以睡眠 2G 微秒或 ~33 分钟，这似乎太短了。
	 */
#ifdef SLEEP_ON_ASSERT
	sleep(1000000);
#endif

	abort();
}
